home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Offline Browsing / HTTrack.exe / data1.cab / Sources / src / htsback.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-28  |  73.7 KB  |  1,940 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       backing system (multiple socket download)              */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htsback.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htsnet.h"
  43. #include "htsthread.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. /* END specific definitions */
  48.  
  49. //#if HTS_WIN
  50. #include "htsftp.h"
  51. //#endif
  52.  
  53. #if HTS_WIN
  54. #ifndef __cplusplus
  55. // DOS
  56. #include <process.h>    /* _beginthread, _endthread */
  57. #endif
  58. #else
  59. #endif
  60.  
  61. #undef test_flush
  62. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  63.  
  64. // ---
  65. // routines de backing
  66. // retourne l'index d'un lien dans un tableau de backing
  67. int back_index(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  68.   register int i=0;
  69.   register int index=-1;
  70.   while( i<back_max ) {
  71.     if (back[i].status>=0)    // rΘception OU prΩt
  72.       if (strfield2(back[i].url_adr,adr)) {
  73.         if (strcmp(back[i].url_fil,fil)==0) {
  74.           if (index==-1)    /* first time we meet, store it */
  75.             index=i;
  76.           else if (strcmp(back[i].url_sav,sav)==0) {  /* oops, check sav too */
  77.             index=i;
  78.             return index;
  79.           }
  80.         }
  81.       }
  82.     i++;
  83.   }
  84.   return index;
  85. }
  86.  
  87. // nombre d'entrΘes libres dans le backing
  88. int back_available(lien_back* back,int back_max) {
  89.   int i;
  90.   int nb=0;
  91.   for(i=0;i<back_max;i++)
  92.     if (back[i].status==-1)     /* libre */
  93.       nb++;
  94.   return nb;
  95. }
  96.  
  97. // retourne estimation de la taille des html et fichiers stockΘs en mΘmoire
  98. LLint back_incache(lien_back* back,int back_max) {
  99.   int i;
  100.   LLint sum=0;
  101.   for(i=0;i<back_max;i++)
  102.     if (back[i].status!=-1)
  103.       if (back[i].r.adr)       // ne comptabilier que les blocs en mΘmoire
  104.         sum+=max(back[i].r.size,back[i].r.totalsize);
  105.   return sum;
  106. }
  107.  
  108. // le lien a-t-il ΘtΘ mis en backing?
  109. HTS_INLINE int back_exist(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  110.   return (back_index(back,back_max,adr,fil,sav)>=0);
  111. }
  112.  
  113. // nombre de sockets en tΓche de fond
  114. int back_nsoc(lien_back* back,int back_max) {
  115.   int n=0;
  116.   int i;
  117.   for(i=0;i<back_max;i++)
  118.     if (back[i].status>0)    // rΘception uniquement
  119.       n++;
  120.  
  121.   return n;
  122. }
  123.  
  124. // effacer entrΘe
  125. int back_delete(lien_back* back,int p) {
  126.   if (p>=0) {    // on sait jamais..
  127.     // VΘrificateur d'intΘgritΘ
  128.     #if DEBUG_CHECKINT
  129.     _CHECKINT(&back[p],"Appel back_delete")
  130.     #endif
  131. #if HTS_DEBUG_CLOSESOCK
  132.     char info[256];
  133.     sprintf(info,"back_delete: #%d\n",p);
  134.     DEBUG_W2(info);
  135. #endif
  136.  
  137.     // LibΘrer tous les sockets, handles, buffers..
  138.     if (back[p].r.soc!=INVALID_SOCKET) {
  139. #if HTS_DEBUG_CLOSESOCK
  140.       DEBUG_W("back_delete: deletehttp\n");
  141. #endif
  142.       deletehttp(&back[p].r);
  143.       back[p].r.soc=INVALID_SOCKET;
  144.     }
  145.     if (back[p].r.adr!=NULL) {  // reste un bloc α dΘsallouer
  146.       freet(back[p].r.adr);
  147.       back[p].r.adr=NULL;
  148.     }
  149.     if (back[p].chunk_adr!=NULL) {  // reste un bloc α dΘsallouer
  150.       freet(back[p].chunk_adr);
  151.       back[p].chunk_adr=NULL;
  152.       back[p].chunk_size=0;
  153.       back[p].is_chunk=0;
  154.     }
  155.     if (back[p].r.is_file) {  // fermer fichier entrΘe
  156.       if (back[p].r.fp!=NULL) {
  157.         fclose(back[p].r.fp);
  158.         back[p].r.fp=NULL;
  159.       }
  160.     }
  161.     if (back[p].r.is_write) {     // ecriture directe
  162.       if (back[p].r.out!=NULL) {  // fermer fichier sortie
  163.         fclose(back[p].r.out);
  164.         back[p].r.out=NULL;
  165.       }
  166.       
  167.       /* Θcrire date "remote" */
  168.       if (strnotempty(back[p].url_sav))          // normalement existe si on a un fichier de sortie
  169.       if (strnotempty(back[p].r.lastmodified))   // last-modified existe
  170.       if (fexist(back[p].url_sav))          // ainsi que le fichier
  171.         set_filetime_rfc822(back[p].url_sav,back[p].r.lastmodified);
  172.  
  173.       /* executer commande utilisateur aprΦs chargement du fichier */
  174.       usercommand(0,NULL,back[p].url_sav);
  175.       back[p].r.is_write=0;
  176.     }
  177.     
  178.     // Tout nettoyer
  179.     bzero((char *)(&back[p]),sizeof(lien_back));  
  180.     back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  181.     
  182.     // Le plus important: libΘrer le champ
  183.     back[p].status=-1;
  184.   }
  185.   return 0;
  186. }
  187.  
  188. /* Space left on backing stack */
  189. int back_stack_available(lien_back* back,int back_max) {
  190.   int p=0,n=0;
  191.   for( ; p < back_max ; p++ )
  192.     if ( back[p].status == -1 )
  193.       n++;
  194.   return n;
  195. }
  196.  
  197. // ajouter un lien en backing
  198. int back_add(lien_back* back,int back_max,httrackp* opt,cache_back* cache,char* adr,char* fil,char* save,char* referer_adr,char* referer_fil,int test,short int* pass2_ptr) {
  199.   int p=0;
  200.  
  201.   // vΘrifier cohΘrence de adr et fil (non vide!)
  202.   if (strnotempty(adr)==0) {
  203.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  204.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: adr is empty for back_add"LF);
  205.     }
  206.     return -1;    // erreur!
  207.   }
  208.   if (strnotempty(fil)==0) {
  209.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  210.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: fil is empty for back_add"LF);
  211.     }
  212.     return -1;    // erreur!
  213.   }
  214.   // FIN vΘrifier cohΘrence de adr et fil (non vide!)
  215.  
  216.   // rechercher emplacement
  217.   while((p<back_max) && back[p].status!=-1) p++;
  218.   if (back[p].status==-1) {    // ok on a de la place
  219.     back[p].send_too[0]='\0';  // Θventuels paramΦtres supplΘmentaires α transmettre au serveur
  220.  
  221.     // ne sert α rien normalement
  222.     if (back[p].r.soc!=INVALID_SOCKET) {
  223. #if HTS_DEBUG_CLOSESOCK
  224.       DEBUG_W("back_add: deletehttp\n");
  225. #endif
  226.       deletehttp(&back[p].r);
  227.     }
  228.  
  229.     // effacer r
  230.     bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  231.  
  232.     // crΘer entrΘe
  233.     strcpy(back[p].url_adr,adr);
  234.     strcpy(back[p].url_fil,fil);
  235.     strcpy(back[p].url_sav,save);
  236.     back[p].pass2_ptr=pass2_ptr;
  237.     // copier referer si besoin
  238.     strcpy(back[p].referer_adr,"");
  239.     strcpy(back[p].referer_fil,"");
  240.     if ((referer_adr) && (referer_fil)) {       // existe
  241.       if ((strnotempty(referer_adr)) && (strnotempty(referer_fil))) {   // non vide
  242.         if (referer_adr[0]!='!') {    // non dΘtruit
  243.           if (strcmp(referer_adr,"file://")) {      // PAS file://
  244.             if (strcmp(referer_adr,"primary")) {      // pas referer 1er lien
  245.               strcpy(back[p].referer_adr,referer_adr);
  246.               strcpy(back[p].referer_fil,referer_fil);
  247.             }
  248.           }
  249.         }
  250.       }
  251.     }
  252.     // sav ne sert α rien pour le moment
  253.     back[p].r.size=0;                   // rien n'a encore ΘtΘ chargΘ
  254.     back[p].r.soc=INVALID_SOCKET;       // pas de socket
  255.     back[p].r.adr=NULL;                 // pas de bloc de mΘmoire
  256.     back[p].r.is_write=0;               // α priori stockage en mΘmoire
  257.     back[p].maxfile_html=opt->maxfile_html;
  258.     back[p].maxfile_nonhtml=opt->maxfile_nonhtml;
  259.     back[p].testmode=test;              // mode test?
  260.     if (!opt->http10)                 // option "forcer 1.0" dΘsactivΘe
  261.       back[p].http11=1;               // autoriser http/1.1
  262.     back[p].head_request=0;
  263.     if (strcmp(back[p].url_sav,BACK_ADD_TEST)==0)    // HEAD
  264.       back[p].head_request=1;
  265.     else if (strcmp(back[p].url_sav,BACK_ADD_TEST2)==0)    // test en GET
  266.       back[p].head_request=2;       // test en get
  267.  
  268.     // tester cache
  269.     if ((strcmp(adr,"file://"))           /* pas fichier */
  270.       && ( (!test) || (cache->type==1) )   /* cache prioritaire, laisser passer en test! */
  271.       && ( (strnotempty(save)) || (strcmp(fil,"/robots.txt")==0) ) ) {  // si en test on ne doit pas utiliser le cache sinon telescopage avec le 302..
  272.       //if ((!test) && (strcmp(adr,"file://")) 
  273.       //if ((!test) && (strncmp(adr,"ftp://",6)) && (strcmp(adr,"file://")) 
  274. #if HTS_FAST_CACHE
  275.       int hash_pos;
  276.       int hash_pos_return=0;
  277. #else
  278.       char* a=NULL;
  279. #endif
  280. #if HTS_FAST_CACHE
  281.       if (cache->hash) { 
  282. #else
  283.       if (cache->use) { 
  284. #endif
  285.         char buff[HTS_URLMAXSIZE*4];
  286. #if HTS_FAST_CACHE
  287.         strcpy(buff,adr); strcat(buff,fil);
  288.         hash_pos_return=inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&hash_pos);
  289. #else
  290.         buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  291.         a=strstr(cache->use,buff);
  292. #endif
  293.         
  294.         // Ok, notΘ en cache->. mais bien prΘsent dans le cache ou sur disque?
  295. #if HTS_FAST_CACHE
  296.         if (hash_pos_return) {
  297. #else
  298.         if (a) {
  299. #endif
  300.           if (!test) {      // non mode test
  301. #if HTS_FAST_CACHE
  302.             int pos=hash_pos;
  303. #else
  304.             int pos=-1;
  305.             a+=strlen(buff);
  306.             sscanf(a,"%d",&pos);    // lire position
  307. #endif
  308.             if (pos<0) {    // pas de mise en cache data, vΘrifier existence
  309.               if (fsize(antislash(save)) <= 0) {  // fichier existe pas ou est vide!
  310. #if HTS_FAST_CACHE
  311.                 hash_pos_return=0;
  312. #else
  313.                 a=NULL;    
  314. #endif
  315.                 // dΘvalider car non prΘsent sur disque dans structure originale!!!
  316.                 // sinon, le fichier est ok α priori, mais on renverra un if-modified-since pour
  317.                 // en Ωtre s√r
  318.                 if (opt->norecatch) {              // tester norecatch
  319.                   if (!fexist(antislash(save))) {  // fichier existe pas mais dΘclarΘ: on l'a effacΘ
  320.                     FILE* fp=fopen(antislash(save),"wb");
  321.                     if (fp) fclose(fp);
  322.                     if (opt->log!=NULL) {
  323.                       fspc(opt->log,"warning"); fprintf(opt->log,"File must have been erased by user, ignoring: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  324.                     }
  325.                   }
  326.                 }
  327.               }
  328.             }
  329.           }
  330.         }
  331.         //
  332.       } else
  333. #if HTS_FAST_CACHE
  334.         hash_pos_return=0;
  335. #else
  336.         a=NULL;
  337. #endif
  338.  
  339.       // Existe pas en cache, ou bien pas de cache prΘsent
  340. #if HTS_FAST_CACHE
  341.       if (hash_pos_return) {  // OK existe en cache (et donnΘes aussi)!
  342. #else
  343.       if (a!=NULL) {  // OK existe en cache (et donnΘes aussi)!
  344. #endif
  345.         if (cache->type==1) {   // cache prioritaire (pas de test if-modified..)
  346.                                // dans ce cas on peut Θgalement lire des rΘponses cachΘes comme 404,302... 
  347.           // lire dans le cache
  348.           if (!test)
  349.             back[p].r=cache_read(opt,cache,adr,fil,save);
  350.           else
  351.             back[p].r=cache_read(opt,cache,adr,fil,NULL);       // charger en tΩte uniquement du cache
  352.           if (!back[p].r.location) 
  353.             back[p].r.location=back[p].location_buffer;
  354.           else {    /* recopier */
  355.             strcpy(back[p].location_buffer,back[p].r.location);
  356.             back[p].r.location=back[p].location_buffer;
  357.           }
  358.  
  359.           /* Interdiction taille par le wizard? --> dΘtruire */
  360.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  361.             if (!back_checksize(opt,&back[p],0)) {
  362.               back[p].status=0;  // FINI
  363.               back[p].r.statuscode=-1;
  364.               if (!back[p].testmode)
  365.                 strcpy(back[p].r.msg,"Cached file skipped (too big)");
  366.               else
  367.                 strcpy(back[p].r.msg,"Test: Cached file skipped  (too big)");
  368.               return 0;
  369.             }
  370.           }
  371.  
  372.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  373.             if ((opt->debug>0) && (opt->log!=NULL)) {
  374.               if (!test) {
  375.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately loaded from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  376.               } else {
  377.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately tested from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  378.               }
  379.             }
  380.             back[p].r.notmodified=1;    // fichier non modifiΘ
  381.             back[p].status=0;  // OK prΩt
  382.             //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  383.             return 0;
  384.           } else {  // erreur
  385.             // effacer r
  386.             bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  387.             // et continuer (chercher le fichier)
  388.           }
  389.           
  390.         } else if (cache->type==2) {    // si en cache, demander de tester If-Modified-Since
  391.           htsblk* r=cache_header(opt,cache,adr,fil);
  392.  
  393.           /* Interdiction taille par le wizard? */
  394.           {
  395.             LLint save_totalsize=back[p].r.totalsize;
  396.             back[p].r.totalsize=r->totalsize;
  397.             if (!back_checksize(opt,&back[p],1)) {
  398.               r=NULL;
  399.               //
  400.               back[p].status=0;  // FINI
  401.               deletehttp(&back[p].r); back[p].r.soc=INVALID_SOCKET;
  402.               if (!back[p].testmode)
  403.                 strcpy(back[p].r.msg,"File too big");
  404.               else
  405.                 strcpy(back[p].r.msg,"Test: File too big");
  406.               return 0;
  407.             }
  408.             back[p].r.totalsize=save_totalsize;
  409.           }
  410.           
  411.           if (r) {
  412.             if (r->statuscode==200) {     // uniquement des 200 (OK)
  413.               if (strnotempty(r->etag)) {  // ETag (RFC2616)
  414.                 if (strnotempty(r->lastmodified))
  415.                   sprintf(back[p].send_too,"If-None-Match: %s\r\nIf-Modified-Since: %s\r\n",r->etag,r->lastmodified);
  416.                 else
  417.                   sprintf(back[p].send_too,"If-None-Match: %s\r\n",r->etag);
  418.               }
  419.               else if (strnotempty(r->lastmodified))
  420.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",r->lastmodified);
  421.               else if (strnotempty(cache->lastmodified))
  422.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  423.  
  424.               /* this is an update of a file */
  425.               if (strnotempty(back[p].send_too))
  426.                 back[p].is_update=1;
  427.  
  428.             }
  429.              /* else if (strnotempty(cache->lastmodified))
  430.               sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  431.              */
  432.           }
  433. #if DEBUGCA
  434.           printf("..is modified test %s\n",back[p].send_too);
  435. #endif
  436.         } 
  437.         // Okay, pas trouvΘ dans le cache
  438.         // Et si le fichier existe sur disque?
  439.         // Pas dans le cache: fichier n'a pas ΘtΘ transfΘrΘ du tout, donc pas sur disque?
  440.       } else {
  441.         if (fexist(save)) {    // fichier existe? aghl!
  442.           LLint sz=fsize(save);
  443.           // Bon, lα il est possible que le fichier ait ΘtΘ partiellement transfΘrΘ
  444.           // (s'il l'avait ΘtΘ en totalitΘ il aurait ΘtΘ inscrit dans le cache ET existerait sur disque)
  445.           // PAS de If-Modified-Since, on a pas connaissance des donnΘes α la date du cache
  446.           // On demande juste les donnΘes restantes si le date est valide (206), tout sinon (200)
  447.           if ((ishtml(save) != 1) && (ishtml(back[p].url_fil)!=1)) {   // NON HTML (liens changΘs!!)
  448.             if (sz>0) {    // Fichier non vide? (question bΩte, sinon on transfert tout!)
  449.               if (strnotempty(cache->lastmodified)) {     /* pas de If-.. possible */
  450.                 /*if ( (!opt->http10) && (strnotempty(cache->lastmodified)) ) { */    /* ne pas forcer 1.0 */
  451. #if DEBUGCA
  452.                 printf("..if unmodified since %s size "LLintP"\n",cache->lastmodified,(LLint)sz);
  453. #endif
  454.                 if ((opt->debug>1) && (opt->log!=NULL)) {
  455.                   fspc(opt->log,"debug"); fprintf(opt->log,"File partially present ("LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  456.                 }
  457.                 
  458.                 /* impossible - don't have etag or date
  459.                 if (strnotempty(back[p].r.etag)) {  // ETag (RFC2616)
  460.                 sprintf(back[p].send_too,"If-None-Match: %s\r\n",back[p].r.etag);
  461.                 back[p].http11=1;    // En tΩte 1.1
  462.                 } else if (strnotempty(back[p].r.lastmodified)) {
  463.                 sprintf(back[p].send_too,"If-Unmodified-Since: %s\r\n",back[p].r.lastmodified);
  464.                 back[p].http11=1;    // En tΩte 1.1
  465.                 } else 
  466.                 */
  467.                 if (strlen(cache->lastmodified)) {
  468.                   sprintf(back[p].send_too,
  469.                     "If-Unmodified-Since: %s\r\nRange: bytes="LLintP"-\r\n"
  470.                     ,cache->lastmodified,(LLint)sz);
  471.                   back[p].http11=1;    // En tΩte 1.1
  472.                   back[p].range_req_size=sz;
  473.                 } else {
  474.                   if ((opt->debug>0) && (opt->errlog!=NULL)) {
  475.                     fspc(opt->log,"warning"); fprintf(opt->log,"Could not find timestamp for partially present file, restarting (lost "LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  476.                   }
  477.                 }
  478.                 
  479.               } else { 
  480.                 if ((opt->debug>0) && (opt->errlog!=NULL)) {
  481.                   fspc(opt->errlog,"warning");
  482.                   /*
  483.                   if (opt->http10)
  484.                   fprintf(opt->errlog,"File partially present (%d bytes) retransfered due to HTTP/1.0 settings: %s%s"LF,sz,back[p].url_adr,back[p].url_fil);
  485.                   else
  486.                   */
  487.                   fprintf(opt->errlog,"File partially present ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  488.                   test_flush;
  489.                 }
  490.                 /* Sinon requΩte normale... */
  491.                 back[p].http11=0;
  492.               }
  493.             } else if (opt->norecatch) {              // tester norecatch
  494.               filenote(save,NULL);       // ne pas purger tout de mΩme
  495.               back[p].status=0;  // OK prΩt
  496.               back[p].r.statuscode=-1;  // erreur
  497.               strcpy(back[p].r.msg,"Null-size file not recaught");
  498.               return 0;
  499.             }
  500.           } else {
  501.             if ((opt->debug>0) && (opt->errlog!=NULL)) {
  502.               fspc(opt->errlog,"warning");
  503.               fprintf(opt->errlog,"HTML file ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  504.               test_flush;
  505.             }
  506.             /* Sinon requΩte normale... */
  507.             back[p].http11=0;
  508.           }
  509.         }
  510.       }
  511.     }
  512.  
  513.  
  514.     {
  515.       ///htsblk r;   non directement dans la structure-rΘponse!
  516.       T_SOC soc;
  517.       
  518.       // ouvrir liaison, envoyer requΦte
  519.       // ne pas traiter ou recevoir l'en tΩte immΘdiatement
  520.       bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  521.       // recopier proxy
  522.       bcopy((char*) &opt->proxy,(char*) &(back[p].r.req.proxy), sizeof(opt->proxy));
  523.       // et user-agent
  524.       strcpy(back[p].r.req.user_agent,opt->user_agent);
  525.       strcpy(back[p].r.req.lang_iso,opt->lang_iso);
  526.       back[p].r.req.user_agent_send=opt->user_agent_send;
  527.       // et http11
  528.       back[p].r.req.http11=back[p].http11;
  529.  
  530.       // mode ftp, court-circuit!
  531.       if (strncmp(back[p].url_adr,"ftp://",6)==0) {
  532.         if (back[p].testmode) {
  533.           if ((opt->debug>1) && (opt->errlog!=NULL)) {
  534.             fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: forbidden test with ftp link for back_add"LF);
  535.           }
  536.           return -1;    // erreur pas de test permis
  537.         }
  538.         if (!(back[p].r.req.proxy.active && opt->ftp_proxy)) { // connexion directe, gΘrΘe en thread
  539.           back[p].status=1000;   // connexion ftp
  540. #if USE_BEGINTHREAD
  541.           launch_ftp(&(back[p]));
  542. #else
  543.           {
  544.             char nid[32];
  545.             sprintf(nid,"htsftp%d-in_progress.lock",p);
  546.             strcpy(back[p].location_buffer,fconcat(opt->path_log,nid));
  547.           }
  548.           launch_ftp(&(back[p]),back[p].location_buffer,opt->exec);
  549. #endif
  550.           return 0;
  551.         }
  552.       }
  553.       
  554. #if HTS_XGETHOST
  555. #if HDEBUG
  556.       printf("back_solve..\n");
  557. #endif
  558.       back[p].status=101;    // tentative de rΘsolution du nom de host
  559.       soc=INVALID_SOCKET;    // pas encore ouverte
  560.       back_solve(&back[p]);  // prΘparer
  561.       if (host_wait(&back[p])) {  // prΩt, par ex fichier ou dispo dans dns
  562. #if HDEBUG
  563.       printf("ok, dns cache ready..\n");
  564. #endif
  565.         soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  566.         if (soc==INVALID_SOCKET) {
  567.           back[p].status=0;  // fini, erreur
  568.         }
  569.       }
  570. //
  571. #else
  572. //
  573. #if CNXDEBUG
  574.       printf("XFopen..\n");
  575. #endif
  576.  
  577.       if (strnotempty(back[p].send_too))    // envoyer un if-modified-since
  578. #if HTS_XCONN
  579.       soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  580. #else
  581.       soc=http_xfopen(0,0,1,back[p].send_too,adr,fil,&(back[p].r));
  582. #endif
  583.       else
  584. #if HTS_XCONN
  585.         soc=http_xfopen(test,0,0,NULL,adr,fil,&(back[p].r));
  586. #else
  587.       soc=http_xfopen(test,0,1,NULL,adr,fil,&(back[p].r));
  588. #endif
  589. #endif
  590.       if (opt->timeout>0) {    // gestion du opt->timeout
  591.         back[p].timeout=opt->timeout;
  592.         back[p].timeout_refresh=time_local();
  593.       } else {
  594.         back[p].timeout=-1;    // pas de gestion (default)
  595.       }
  596.       
  597.       if (opt->rateout>0) {    // gestion d'un taux minimum de transfert tolΘrΘ
  598.         back[p].rateout=opt->rateout;
  599.         back[p].rateout_time=time_local();
  600.       } else {
  601.         back[p].rateout=-1;    // pas de gestion (default)
  602.       }
  603.  
  604.       // Note: on charge les code-page erreurs (erreur 404, etc) dans le cas o∙ cela est
  605.       // rattrapable (exemple: 301,302 moved xxx -> refresh sur la page!)
  606.       //if ((back[p].statuscode!=200) || (soc<0)) { // ERREUR HTTP/autre
  607.  
  608. #if CNXDEBUG
  609. printf("Xfopen ok, poll..\n");
  610. #endif
  611.  
  612. #if HTS_XGETHOST
  613.     if (soc!=INVALID_SOCKET)
  614.       if (back[p].status==101) {  // pas d'erreur
  615.         if (!back[p].r.is_file)
  616.           back[p].status=100;   // connexion en cours
  617.         else
  618.           back[p].status=1;     // fichier
  619.       }
  620.  
  621. #else
  622.       if (soc==INVALID_SOCKET) { // erreur socket
  623.         back[p].status=0;    // FINI
  624.         //if (back[p].soc!=INVALID_SOCKET) deletehttp(back[p].soc);
  625.         back[p].r.soc=INVALID_SOCKET;
  626.       } else {
  627.         if (!back[p].r.is_file)
  628. #if HTS_XCONN
  629.           back[p].status=100;   // connexion en cours
  630. #else
  631.           back[p].status=99;    // chargement en tΩte en cours
  632. #endif
  633.         else
  634.           back[p].status=1;     // chargement fichier
  635. #if BDEBUG==1
  636.         printf("..loading header\n");
  637. #endif
  638.       }
  639. #endif
  640.       
  641.     }
  642.  
  643.  
  644.     // note: si il y a erreur (404,etc) status=2 (terminΘ/Θchec) mais
  645.     // le lien est considΘrΘ comme traitΘ
  646.     //if (back[p].soc<0)  // erreur
  647.     //  return -1;
  648.  
  649.     return 0;
  650.   } else {
  651.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  652.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: no space left in stack for back_add"LF);
  653.     }
  654.     return -1;    // plus de place
  655.   }
  656. }
  657.  
  658.  
  659.  
  660. #if HTS_XGETHOST
  661. #if USE_BEGINTHREAD
  662. // lancement multithread du robot
  663. PTHREAD_TYPE Hostlookup(void* iadr_p) {
  664.   char iadr[256];
  665.   t_dnscache* cache=_hts_cache();  // adresse du cache
  666.   t_hostent* hp;
  667.   int error_found=0;
  668.  
  669.   // recopier (aprΦs id:pass)
  670. #if DEBUGDNS 
  671.   printf("resolv in background: %s\n",jump_identification(iadr_p));
  672. #endif
  673.   strcpy(iadr,jump_identification(iadr_p));
  674.   // couper Θventuel :
  675.   {
  676.     char *a;
  677.     if ( (a=strchr(iadr,':')) )
  678.       *a='\0';
  679.   }
  680.   freet(iadr_p);
  681.  
  682.   // attendre que le cache dns soit prΩt
  683.   while(_hts_lockdns(-1));  // attendre libΘration
  684.   _hts_lockdns(1);          // locker
  685.   while(cache->n) {
  686.     if (strcmp(cache->iadr,iadr)==0) {
  687.       error_found=1;
  688.     }
  689.     cache=cache->n;    // calculer queue
  690.   }
  691.   if (strcmp(cache->iadr,iadr)==0) {
  692.     error_found=1;
  693.   }
  694.  
  695.   if (!error_found) {
  696.     // en gros copie de hts_gethostbyname sans le return
  697.     cache->n=(t_dnscache*) calloct(1,sizeof(t_dnscache));
  698.     if (cache->n!=NULL) {
  699.       strcpy(cache->n->iadr,iadr);
  700.       cache->n->host_length=0;        /* pour le moment rien */
  701.       cache->n->n=NULL;
  702.       _hts_lockdns(0);          // dΘlocker
  703.       
  704.       /* resolve */
  705. #if DEBUGDNS 
  706.       printf("gethostbyname() in progress for %s\n",iadr);
  707. #endif
  708.       hp=gethostbyname(iadr);  // rΘsolution IP
  709.       
  710.       /* okay, result */
  711.       if (hp!=NULL) {
  712.         bcopy(hp->h_addr,cache->n->host_addr,hp->h_length);       // write first
  713.         cache->n->host_length=hp->h_length;                       // then write this
  714.       } else {
  715.         cache->n->host_addr[0]='\0';
  716.         cache->n->host_length=-1;             // dΘclarer erreur dans le dns
  717.       }
  718.     } else 
  719.     _hts_lockdns(0);          // dΘlocker
  720.   } else {
  721. #if DEBUGDNS 
  722.     printf("aborting resolv for %s (found)\n",iadr);
  723. #endif
  724.     _hts_lockdns(0);          // dΘlocker
  725.   }
  726.   // fin de copie de hts_gethostbyname
  727.  
  728. #if DEBUGDNS 
  729.   printf("quitting resolv for %s (result: %d)\n",iadr,(cache->n!=NULL)?cache->n->host_length:(-999));
  730. #endif
  731.  
  732.   return PTHREAD_RETURN;     /* _endthread implied  */
  733. }
  734. #endif
  735.  
  736. // attendre que le host (ou celui du proxy) ait ΘtΘ rΘsolu
  737. // si c'est un fichier, la rΘsolution est immΘdiate
  738. // idem pour ftp://
  739. void back_solve(lien_back* back) {
  740.   if ((strcmp(back->url_adr,"file://")) && (strncmp(back->url_adr,"ftp://",6))) {
  741.   //## if (back->url_adr[0]!=lOCAL_CHAR) {  // qq chose α prΘparer
  742.     char* a;
  743.     if (!(back->r.req.proxy.active))
  744.       a=back->url_adr;
  745.     else
  746.       a=back->r.req.proxy.name;
  747.     if (!hts_dnstest(a)) {   // non encore testΘ!..
  748.       // inscire en thread
  749. #if HTS_WIN
  750.       // Windows
  751. #if USE_BEGINTHREAD
  752.       {
  753.         char* p = calloct(strlen(a)+2,1);
  754.         if (p) {
  755.           strcpy(p,a);
  756.           _beginthread( Hostlookup , 0, p );
  757.         }
  758.       }
  759. #else
  760.       /*t_hostent* h=*/
  761.       /*hts_gethostbyname(a);*/  // calcul
  762. #endif
  763. #else
  764. #if USE_BEGINTHREAD
  765.         char* p = calloct(strlen(a)+2,1);
  766.         if (p) {
  767.           strcpy(p,a);
  768.           _beginthread( Hostlookup , 0, p );
  769.         }
  770. #else
  771.       // Sous Unix, le gethostbyname() est bloquant..
  772.       /*t_hostent* h=*/
  773.       /*hts_gethostbyname(a);*/  // calcul
  774. #endif
  775. #endif
  776.     }
  777.   }
  778. }
  779.  
  780. // dΘtermine si le host a pu Ωtre rΘsolu
  781. int host_wait(lien_back* back) {
  782.   if ((strcmp(back->url_adr,"file://")) && (strncmp(back->url_adr,"ftp://",6))) {
  783.   //## if (back->url_adr[0]!=lOCAL_CHAR) {
  784.     if (!(back->r.req.proxy.active)) {
  785.       return (hts_dnstest(back->url_adr));
  786.     } else {
  787.       return (hts_dnstest(back->r.req.proxy.name));      
  788.     }
  789.   } else return 1;    // prΩt, fichier local
  790. }
  791. #endif
  792.  
  793.  
  794. // Θlimine les fichiers non html en backing (anticipation)
  795. // cleanup non-html files in backing to save backing space
  796. // and allow faster "save in cache" operation
  797. void back_clean(httrackp* opt,cache_back* cache,lien_back* back,int back_max) {
  798.   int i;
  799.   for(i=0;i<back_max;i++) {
  800.     if (back[i].status == 0) {                                   // ready
  801.       if (!back[i].testmode) {                                   // not test mode
  802.         if (strnotempty(back[i].url_sav)) {                      // filename exists
  803.           if (back[i].r.is_write) {                              // not in memory (on disk, ready)
  804.             if (back[i].r.size>0) {                              // size>0
  805.               if (back[i].r.statuscode==200) {                   // HTTP "OK"
  806.                 if (!is_hypertext_mime(back[i].r.contenttype)) { // not HTML/hypertext
  807.                   if (!may_be_hypertext_mime(back[i].r.contenttype)) { // may NOT be parseable mime type
  808.                     if (back[i].pass2_ptr) {
  809.                       cache_mayadd(opt,cache,&back[i].r,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  810.                       *back[i].pass2_ptr=-1;  // Done!
  811.                       back_delete(back,i);    // Delete backing entry
  812.                       HTS_STAT.stat_bytes+=back[i].r.size;
  813.                       HTS_STAT.stat_files++;
  814.                       if ( (!back[i].r.notmodified) && (opt->is_update) ) { 
  815.                         HTS_STAT.stat_updated_files++;       // page modifiΘe
  816.                       }
  817.                     }
  818.                   }
  819.                 }
  820.               }
  821.             }
  822.           }
  823.         }
  824.       }
  825.     }
  826.   }            
  827. }
  828.  
  829.  
  830. // attente (gestion des buffers des sockets)
  831. void back_wait(lien_back* back,int back_max,httrackp* opt,cache_back* cache,double stat_timestart) {
  832.   int i;
  833.   T_SOC nfds=INVALID_SOCKET;
  834.   fd_set fds,fds_c,fds_e;     // fds pour lecture, connect (write), et erreur
  835.   struct timeval tv;
  836.   int do_wait=0;
  837.   int gestion_timeout=0;
  838.   int busy=0;    // pas de donnΘes pour le moment   
  839. #if HTS_ANALYSTE
  840.   int max_loop=8;  // nombre de boucles max α parcourir..
  841.   int max_loop_chk=0;
  842. #else
  843.   int max_loop=8;  // nombre de boucles max α parcourir..
  844. #endif
  845.  
  846.  
  847. #if 1
  848.   // Cleanup the stack to save space!
  849.   back_clean(opt,cache,back,back_max);
  850. #endif
  851.  
  852.   // recevoir tant qu'il y a des donnΘes (avec un maximum de max_loop boucles)
  853.   do_wait=0;
  854.   gestion_timeout=0;
  855.   do {
  856.     int max_c;
  857.     busy=0;
  858.  
  859.     check_rate(stat_timestart,opt->maxrate);    // vΘrifier taux de transfert
  860.     // inscrire les sockets actuelles, et rechercher l'ID la plus ΘlevΘe
  861.     FD_ZERO(&fds);
  862.     FD_ZERO(&fds_c);
  863.     FD_ZERO(&fds_e);
  864.  
  865.     max_c=1;
  866.     for(i=0;i<back_max;i++) {
  867.  
  868.       // en cas de gestion du connect prΘemptif
  869. #if HTS_XCONN
  870.       if (back[i].status==100) {      // connexion
  871.         do_wait=1;
  872.  
  873.         // noter socket write
  874.         FD_SET(back[i].r.soc,&fds_c);
  875.         
  876.         // noter socket erreur
  877.         FD_SET(back[i].r.soc,&fds_e);
  878.  
  879.         // calculer max
  880.         if (max_c) {
  881.           max_c=0;
  882.           nfds=back[i].r.soc;
  883.         } else if (back[i].r.soc>nfds) {
  884.           // ID socket la plus ΘlevΘe
  885.           nfds=back[i].r.soc;
  886.         }
  887.         
  888.       } else
  889. #endif
  890. #if HTS_XGETHOST
  891.       if (back[i].status==101) {      // attente
  892.         // rien α faire..
  893.       } else
  894. #endif
  895.       // poll pour la lecture sur les sockets
  896.       if ((back[i].status>0) && (back[i].status<100)) {  // en rΘception http
  897.             
  898. #if BDEBUG==1
  899.         //printf("....socket in progress: %d\n",back[i].r.soc);
  900. #endif
  901.         // non local et non ftp
  902.         if (strncmp(back[i].url_adr,"file://",7)) {
  903.         //## if (back[i].url_adr[0]!=lOCAL_CHAR) {
  904.           
  905.           // vΘrification de sΘcuritΘ
  906.           if ((back[i].r.soc!=INVALID_SOCKET) && (!back[i].r.is_file)) {  // hey, you never know..
  907.             do_wait=1;
  908.             
  909.             // noter socket read
  910.             FD_SET(back[i].r.soc,&fds);
  911.             
  912.             // noter socket error
  913.             FD_SET(back[i].r.soc,&fds_e);
  914.             
  915.             // calculer max
  916.             if (max_c) {
  917.               max_c=0;
  918.               nfds=back[i].r.soc;
  919.             } else if (back[i].r.soc>nfds) {
  920.               // ID socket la plus ΘlevΘe
  921.               nfds=back[i].r.soc;
  922.             }
  923.           } 
  924. #if WIDE_DEBUG
  925.           else {
  926.             DEBUG_W("PANIC!!! Socket is invalid in a poll test!\n");
  927.           }
  928. #endif
  929.           
  930.         }
  931.         
  932.       }
  933.     }    
  934.     nfds++;
  935.     
  936.     if (do_wait) {  // attendre
  937.       // temps d'attente max: 2.5 seconde
  938.       tv.tv_sec=HTS_SOCK_SEC;
  939.       tv.tv_usec=HTS_SOCK_MS;
  940.       
  941. #if BDEBUG==1
  942.       printf("..select\n");
  943. #endif
  944.       
  945.       // poller les sockets-attention au noyau sous Unix..
  946. #if HTS_WIDE_DEBUG    
  947.       DEBUG_W("select\n");
  948. #endif
  949.       select(nfds,&fds,&fds_c,&fds_e,&tv);
  950. #if HTS_WIDE_DEBUG    
  951.       DEBUG_W("select done\n");
  952. #endif      
  953.     }
  954.      
  955.     // recevoir les donnΘes arrivΘes
  956.     for(i=0;i<back_max;i++) {
  957.       
  958.       if (back[i].status>0) {
  959.         if ((back[i].r.soc!=INVALID_SOCKET) && (!back[i].r.is_file)) {  // hey, you never know..
  960.           int err;
  961.           // erreur?
  962.           err=FD_ISSET(back[i].r.soc,&fds_e);        
  963.           if (err) {
  964.             if (back[i].r.soc!=INVALID_SOCKET) {
  965. #if HTS_DEBUG_CLOSESOCK
  966.               DEBUG_W("back_wait: deletehttp\n");
  967. #endif
  968.               deletehttp(&back[i].r);
  969.             }
  970.             back[i].r.soc=INVALID_SOCKET;
  971.             back[i].r.statuscode=-4;
  972.             if (back[i].status==100)
  973.               strcpy(back[i].r.msg,"Connect Error");
  974.             else
  975.               strcpy(back[i].r.msg,"Receive Error");
  976.             back[i].status=0;  // terminΘ
  977.           }
  978.         }
  979.       }
  980.  
  981.       // ---- FLAG WRITE MIS A UN?: POUR LE CONNECT
  982.       if (back[i].status==100) {   // attendre connect
  983.         int dispo=0;
  984.         // vΘrifier l'existance de timeout-check
  985.         if (!gestion_timeout)
  986.           if (back[i].timeout>0)
  987.             gestion_timeout=1;
  988.           
  989.         // connectΘ?
  990.         dispo=FD_ISSET(back[i].r.soc,&fds_c);
  991.         if (dispo) {    // ok
  992.           busy=1;
  993. #if BDEBUG==1
  994.           printf("..connect ok on socket %d\n",back[i].r.soc);
  995. #endif
  996.           /* limit nb. connections/seconds to avoid server overload */
  997.           if (opt->maxconn>0) {
  998.             Sleep(1000/opt->maxconn);
  999.           }
  1000.  
  1001.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1002.             back[i].timeout_refresh=time_local();
  1003.           }
  1004.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1005.             back[i].rateout_time=time_local();
  1006.           }
  1007.           // envoyer header
  1008.           //if (strcmp(back[i].url_sav,BACK_ADD_TEST)!=0)    // vrai get
  1009.           if (!back[i].head_request)
  1010.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1011.           else if (back[i].head_request==2)  // test en GET!
  1012.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1013.           else        // test!
  1014.             http_sendhead(opt->cookie,1,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1015.           back[i].status=99;  // attendre en tΩte maintenant
  1016.         }
  1017.  
  1018.         // attente gethostbyname
  1019.       } 
  1020. #if HTS_XGETHOST
  1021.       else if (back[i].status==101) {  // attendre gethostbyname
  1022. #if DEBUGDNS 
  1023.         //printf("status 101 for %s\n",back[i].url_adr);
  1024. #endif
  1025.  
  1026.         if (!gestion_timeout)
  1027.           if (back[i].timeout>0)
  1028.             gestion_timeout=1;
  1029.  
  1030.         if (host_wait(&back[i])) {    // prΩt
  1031.           back[i].status=100;        // attente connexion
  1032.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1033.             back[i].timeout_refresh=time_local();
  1034.           }
  1035.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1036.             back[i].rateout_time=time_local();
  1037.           }
  1038.  
  1039.           back[i].r.soc=http_xfopen(0,0,0,back[i].send_too,back[i].url_adr,back[i].url_fil,&(back[i].r));
  1040.           if (back[i].r.soc==INVALID_SOCKET) {
  1041.             back[i].status=0;  // fini, erreur
  1042.             if (back[i].r.soc!=INVALID_SOCKET) {
  1043. #if HTS_DEBUG_CLOSESOCK
  1044.               DEBUG_W("back_wait(2): deletehttp\n");
  1045. #endif
  1046.               deletehttp(&back[i].r);
  1047.             }
  1048.             back[i].r.soc=INVALID_SOCKET;
  1049.             back[i].r.statuscode=-5;
  1050.             if (strnotempty(back[i].r.msg)==0) 
  1051.               strcpy(back[i].r.msg,"Unable to establish host name");
  1052.           }
  1053.         }
  1054.         
  1055.  
  1056.       // ---- FLAG READ MIS A UN?: POUR LA RECEPTION
  1057.       }
  1058. #endif
  1059. #if USE_BEGINTHREAD
  1060.       // ..rien α faire, c'est magic les threads
  1061. #else
  1062.       else if (back[i].status==1000) {  // en rΘception ftp
  1063.         if (!fexist(back[i].location_buffer)) {    // terminΘ
  1064.           FILE* fp;
  1065.           fp=fopen(fconcat(back[i].location_buffer,".ok"),"rb");
  1066.           if (fp) {
  1067.             int j=0;
  1068.             fscanf(fp,"%d ",&(back[i].r.statuscode));
  1069.             while(!feof(fp)) {
  1070.               int c = fgetc(fp);
  1071.               if (c!=EOF)
  1072.                 back[i].r.msg[j++]=c;
  1073.             }
  1074.             back[i].r.msg[j++]='\0';
  1075.             fclose(fp);
  1076.             remove(fconcat(back[i].location_buffer,".ok"));
  1077.             strcpy(fconcat(back[i].location_buffer,".ok"),"");
  1078.           } else {
  1079.             strcpy(back[i].r.msg,"Unknown ftp result, check if file is ok");
  1080.             back[i].r.statuscode=-1;
  1081.           }
  1082.           back[i].status=0;
  1083.         }
  1084.       }
  1085. #endif
  1086.       else if ((back[i].status>0) && (back[i].status<1000)) {  // en rΘception http
  1087.         int dispo=0;
  1088.         
  1089.         // vΘrifier l'existance de timeout-check
  1090.         if (!gestion_timeout)
  1091.           if (back[i].timeout>0)
  1092.             gestion_timeout=1;
  1093.           
  1094.           // donnΘes dispo?
  1095.           //## if (back[i].url_adr[0]!=lOCAL_CHAR)
  1096.           if (strcmp(back[i].url_adr,"file://"))
  1097.             dispo=FD_ISSET(back[i].r.soc,&fds);
  1098.           else dispo=1;
  1099.           
  1100.           if (dispo) {    // donnΘes dispo
  1101.             LLint retour_fread;
  1102.             busy=1;    // on rΘcupΦre encore
  1103. #if BDEBUG==1
  1104.             printf("..data available on socket %d\n",back[i].r.soc);
  1105. #endif
  1106.  
  1107.             
  1108.             // Various hacks to limit re-transfers when updating a mirror
  1109.             if (opt->sizehack) {
  1110.               // We have request for a partial file (with a 'Range: NNN-' header)
  1111.               // and received a complete file notification (200), with 'Content-length: NNN'
  1112.               // it might be possible that we had the complete file
  1113.               // this is the case in *most* cases, so break the connection
  1114.               if (back[i].r.is_write==0) {  // mode mΘmoire
  1115.                 if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1116.                   if (!back[i].testmode) {  // pas mode test
  1117.                     if (strnotempty(back[i].url_sav)) {
  1118.                       if (strcmp(back[i].url_fil,"/robots.txt")) {
  1119.                         if (back[i].r.statuscode==200) {  // 'OK'
  1120.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1121.                             
  1122.                             if (back[i].r.statuscode==200) {      // "OK"
  1123.                               if (back[i].range_req_size>0) {     // but Range: requested
  1124.                                 if (back[i].range_req_size == back[i].r.totalsize) {    // And same size
  1125. #if HTS_DEBUG_CLOSESOCK
  1126.                                   DEBUG_W("back_wait(skip_range): deletehttp\n");
  1127. #endif
  1128.                                   deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1129.                                   back[i].status=0;    // READY
  1130.                                   back[i].r.size=back[i].r.totalsize;
  1131.                                   filenote(back[i].url_sav,NULL);
  1132.                                   // back[i].r.statuscode=304;     // NOT MODIFIED
  1133.                                   if ((opt->debug>1) && (opt->log!=NULL)) {
  1134.                                     fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (reget failed), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1135.                                   }
  1136.                                 }
  1137.                               }
  1138.                             }
  1139.                             
  1140.                           }
  1141.                         }
  1142.                       }
  1143.                     }
  1144.                   }
  1145.                 }
  1146.               }
  1147.             }
  1148.             // END - Various hacks to limit re-transfers when updating a mirror
  1149.  
  1150.  
  1151.  
  1152. #if HTS_DIRECTDISK
  1153.             // Court-circuit:
  1154.             // Peut-on stocker le fichier directement sur disque?
  1155.             // Ahh que ca serait vachement mieux et que ahh que la mΘmoire vous dit merci!
  1156.             if (back[i].status) {
  1157.               if (back[i].r.is_write==0) {  // mode mΘmoire
  1158.                 if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1159.                   if (!back[i].testmode) {  // pas mode test
  1160.                     if (strnotempty(back[i].url_sav)) {
  1161.                       if (strcmp(back[i].url_fil,"/robots.txt")) {
  1162.                         if (back[i].r.statuscode==200) {  // 'OK'
  1163.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1164.                             if (opt->getmode&2) {    // on peut ecrire des non html
  1165.                               back[i].r.is_write=1;    // Θcrire
  1166.                               back[i].r.out=filecreate(back[i].url_sav);
  1167. #if HDEBUG
  1168.                               printf("direct-disk: %s\n",back[i].url_sav);
  1169. #endif
  1170.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1171.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File received from net to disk: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1172.                               }
  1173.                               
  1174.                               if (back[i].r.out==NULL) {
  1175.                                 back[i].r.is_write=0;    // erreur, abandonner
  1176. #if HDEBUG
  1177.                                 printf("..error!\n");
  1178. #endif
  1179.                               }
  1180. #if HTS_WIN==0
  1181.                               else chmod(back[i].url_sav,HTS_ACCESS_FILE);      
  1182. #endif          
  1183.                             } else {  // on coupe tout!
  1184.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1185.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File cancelled (non HTML): %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1186.                               }
  1187.                               back[i].status=0;  // terminΘ
  1188.                               if (!back[i].testmode)
  1189.                                 back[i].r.statuscode=-10;    // EUHH CANCEL
  1190.                               else
  1191.                                 back[i].r.statuscode=-10;    // "TEST OK"
  1192.                               if (back[i].r.soc!=INVALID_SOCKET) {
  1193. #if HTS_DEBUG_CLOSESOCK
  1194.                                 DEBUG_W("back_wait(3): deletehttp\n");
  1195. #endif
  1196.                                 deletehttp(&back[i].r);
  1197.                               }
  1198.                               back[i].r.soc=INVALID_SOCKET;
  1199.                             }
  1200.                           }
  1201.                         }
  1202.                       }
  1203.                     }
  1204.                   }
  1205.                 }
  1206.               }
  1207.             }
  1208. #endif              
  1209.  
  1210.             // rΘception de donnΘes depuis socket ou fichier
  1211.             if (back[i].status) {
  1212.               if (back[i].status==99)  // recevoir caractΦre par caractΦre
  1213.                 retour_fread=http_xfread1(&(back[i].r),0);
  1214.               else if (back[i].status==98) { // recevoir longueur chunk en hexa caractΦre par caractΦre
  1215.                 // backuper pour lire dans le buffer chunk
  1216.                 htsblk r;
  1217.                 bcopy((char*) &(back[i].r), (char*) &r, sizeof(htsblk));
  1218.                 back[i].r.is_write=0;                   // mΘmoire
  1219.                 back[i].r.adr=back[i].chunk_adr;        // adresse
  1220.                 back[i].r.size=back[i].chunk_size;      // taille taille chunk
  1221.                 back[i].r.totalsize=-1;                 // total inconnu
  1222.                 back[i].r.out=NULL;
  1223.                 back[i].r.is_file=0;
  1224.                 //
  1225.                 retour_fread=http_xfread1(&(back[i].r),0);
  1226.                 // modifier et restaurer
  1227.                 back[i].chunk_adr=back[i].r.adr;        // adresse
  1228.                 back[i].chunk_size=back[i].r.size;      // taille taille chunk
  1229.                 bcopy((char*) &r, (char*) &(back[i].r), sizeof(htsblk));    // restaurer vΘritable r
  1230.               }
  1231.               else if (back[i].is_chunk) {         // attention chunk, limiter taille α lire
  1232. #if CHUNKDEBUG==1
  1233.                 printf("read %d bytes\n",(int)min(back[i].r.totalsize-back[i].r.size,TAILLE_BUFFER));
  1234. #endif
  1235.                 retour_fread=http_xfread1(&(back[i].r),(int)min(back[i].r.totalsize-back[i].r.size,TAILLE_BUFFER));
  1236.               } else
  1237.                 retour_fread=http_fread1(&(back[i].r));
  1238.             } else
  1239.               retour_fread=-1;                    // interruption ou annulation interne (peut ne pas Ωtre une erreur)
  1240.             
  1241.             // Si rΘception chunk, tester si on est pas α la fin!
  1242.             if (back[i].status==1) {
  1243.               if (back[i].is_chunk) {     // attendre prochain chunk
  1244.                 if (back[i].r.size==back[i].r.totalsize) {      // fin chunk!
  1245.                   //printf("chunk end at %d\n",back[i].r.size);
  1246.                   back[i].status=98;  // prochain chunk
  1247.                   if (back[i].chunk_adr!=NULL) { freet(back[i].chunk_adr); back[i].chunk_adr=NULL; } back[i].chunk_size=0;
  1248.                   retour_fread=0;       // pas d'erreur
  1249. #if CHUNKDEBUG==1
  1250.                   printf("waiting for next chunk header (soc %d)..\n",back[i].r.soc);
  1251. #endif
  1252.                 }
  1253.               }
  1254.             }
  1255.                           
  1256.             if (retour_fread==-1) {    // erreur rΘception
  1257.               back[i].status=0;    // terminΘ
  1258.               if (back[i].r.soc!=INVALID_SOCKET) {
  1259. #if HTS_DEBUG_CLOSESOCK
  1260.                 DEBUG_W("back_wait(4): deletehttp\n");
  1261. #endif
  1262.                 deletehttp(&back[i].r);
  1263.               }
  1264.               back[i].r.soc=INVALID_SOCKET;
  1265. #if CHUNKDEBUG==1
  1266.               if (back[i].is_chunk)
  1267.                 printf("must be the last chunk for %s (connection closed) - %d/%d\n",back[i].url_fil,back[i].r.size,back[i].r.totalsize);
  1268. #endif
  1269.               //if ((back[i].r.statuscode==-1) && (strnotempty(back[i].r.msg)==0)) {
  1270.               if ((back[i].r.statuscode<0) && (strnotempty(back[i].r.msg)==0)) {
  1271. #if HDEBUG
  1272.                 printf("error interruped: %s\n",back[i].r.adr);
  1273. #endif        
  1274.                 if (back[i].r.size>0)
  1275.                   strcat(back[i].r.msg,"Interrupted transfer");
  1276.                 else
  1277.                   strcat(back[i].r.msg,"No data (connection closed)");
  1278.                 back[i].r.statuscode=-4;
  1279.               }
  1280.  
  1281.               if (back[i].r.totalsize>0) {    // tester totalsize
  1282.               //if ((back[i].r.totalsize>0) && (back[i].status==99)) {    // tester totalsize
  1283.                 if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1284.                   if (!opt->tolerant) {
  1285.                     //#if HTS_CL_IS_FATAL
  1286.                     if (back[i].r.adr) freet(back[i].r.adr); back[i].r.adr=NULL;
  1287.                     if (back[i].r.size<back[i].r.totalsize)
  1288.                       back[i].r.statuscode=-4;        // recatch
  1289.                     sprintf(back[i].r.msg,"Incorrect length ("LLintP" Bytes, "LLintP" expected)",back[i].r.size,back[i].r.totalsize);
  1290.                   } else {
  1291.                     //#else
  1292.                     // Un warning suffira..
  1293.                     if (cache->errlog!=NULL) {
  1294.                       fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1295.                     }
  1296.                     //#endif
  1297.                   }
  1298.                 }
  1299.               }
  1300. #if BDEBUG==1
  1301.               printf("transfer ok\n");
  1302. #endif
  1303.             } else {    // pas d'erreur de rΘception
  1304.               if (back[i].timeout>0) {    // refresh timeout si besoin est
  1305.                 back[i].timeout_refresh=time_local();
  1306.               }
  1307.  
  1308.               // Traitement des en tΩtes chunks ou en tΩtes
  1309.               if (back[i].status==98) {        // rΘception taille chunk en hexa (  aprΦs les en tΩtes, peut ne pas
  1310.                 if (back[i].chunk_size>=2) {
  1311.                   int chunk_size=-1;
  1312.                   // Ωtre prΘsent)
  1313.                   if (back[i].chunk_adr[back[i].chunk_size-1]==10) {    // LF, fin ligne chunk
  1314.                     char chunk_data[64];
  1315.                     if (back[i].chunk_size<32) {      // pas trop gros
  1316.                       back[i].chunk_adr[ back[i].chunk_size-1]='\0';    // octet nul 
  1317.                       strcpy(chunk_data,"");    // hex number
  1318.                       strcat(chunk_data,back[i].chunk_adr);
  1319. #if CHUNKDEBUG==1
  1320.                       printf("chunk received and read: %s\n",chunk_data);
  1321. #endif
  1322.                       if (back[i].r.totalsize<0)
  1323.                         back[i].r.totalsize=0;        // initialiser α 0
  1324.                       if (sscanf(chunk_data,"%x",&chunk_size) == 1) {
  1325.                         back[i].r.totalsize+=chunk_size;    // noter taille
  1326.                         back[i].r.adr=(char*) realloct(back[i].r.adr,(INTsys) back[i].r.totalsize + 1);
  1327.                         if (!back[i].r.adr) {
  1328.                           if (cache->errlog!=NULL) {
  1329.                             fprintf(cache->errlog,"Error: Not enough memory ("LLintP") for %s%s"LF,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1330.                           }
  1331.                         }
  1332. #if CHUNKDEBUG==1
  1333.                         printf("chunk length: %d - next total "LLintP":\n",chunk_size,back[i].r.totalsize);
  1334. #endif
  1335.                       } else                                
  1336.                         if (cache->errlog!=NULL) {
  1337.                           fprintf(cache->errlog,"Warning: Illegal chunk (%s) for %s%s"LF,back[i].chunk_adr,back[i].url_adr,back[i].url_fil);
  1338.                         }
  1339.                     } else {                                  
  1340.                       if (cache->errlog!=NULL) {
  1341.                         fprintf(cache->errlog,"Warning: Chunk too big ("LLintP") for %s%s"LF,back[i].chunk_size,back[i].url_adr,back[i].url_fil);
  1342.                       }
  1343.                     }
  1344.                     
  1345.                     // ok, continuer sur le body
  1346.                     
  1347.                     // si chunk non nul continuer (ou commencer)
  1348.                     if (chunk_size>0) {
  1349.                       back[i].status=1;     // continuer body    
  1350. #if CHUNKDEBUG==1
  1351.                       printf("waiting for body (chunk)\n");
  1352. #endif
  1353.                     } else {                // chunk nul, c'est la fin
  1354. #if CHUNKDEBUG==1
  1355.                       printf("chunk end, total: %d\n",back[i].r.size);
  1356. #endif
  1357.                       back[i].status=0;     // fin    
  1358.                       if (back[i].r.soc!=INVALID_SOCKET) {
  1359. #if HTS_DEBUG_CLOSESOCK
  1360.                         DEBUG_W("back_wait(5): deletehttp\n");
  1361. #endif
  1362.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1363.  
  1364.                         /* Tester totalsize en fin de chunk */
  1365.                         if ((back[i].r.totalsize>0)) {    // tester totalsize
  1366.                           if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1367. #if HTS_CL_IS_FATAL
  1368.                             if (back[i].r.adr) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1369.                             back[i].r.statuscode=-1;
  1370.                             strcpy(back[i].r.msg,"Incorrect length");
  1371. #else
  1372.                             // Un warning suffira..
  1373.                             if (cache->errlog!=NULL) {
  1374.                               fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1375.                             }
  1376. #endif
  1377.                           }
  1378.                         }
  1379.                         
  1380.                       
  1381.                       }
  1382.                     }
  1383.  
  1384.                     // effacer buffer (chunk en tete)
  1385.                     if (back[i].chunk_adr!=NULL) {
  1386.                       freet(back[i].chunk_adr);
  1387.                       back[i].chunk_adr=NULL;
  1388.                       back[i].chunk_size=0;
  1389.                     }
  1390.                   
  1391.                   } // chunk LF?
  1392.                 }  // taille buffer chunk>2
  1393.                 //
  1394.               } else if (back[i].status==99) {        // en tΩtes (avant le chunk si il est prΘsent)
  1395.                 //
  1396.                 if (back[i].r.size>=2) {
  1397.                   if ((back[i].r.adr[back[i].r.size-1]==10) && (back[i].r.adr[back[i].r.size-2]==10)) {
  1398.                     char rcvd[2048];
  1399.                     int ptr=0;
  1400.                     
  1401. #if BDEBUG==1
  1402.                     printf("..ok, header received\n");
  1403. #endif
  1404.                     
  1405.                     // ----------------------------------------
  1406.                     // traiter en-tΩte!
  1407.                     // status-line α rΘcupΘrer
  1408.                     ptr+=binput(back[i].r.adr+ptr,rcvd,2000);
  1409.                     if (strnotempty(rcvd)==0)
  1410.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);    // "certains serveurs buggΘs envoient un \n au dΘbut" (RFC)
  1411.                     
  1412.                     // traiter status-line
  1413.                     treatfirstline(&back[i].r,rcvd);
  1414.                     
  1415. #if HDEBUG
  1416.                     printf("(Buffer) Status-Code=%d\n",back[i].r.statuscode);
  1417. #endif
  1418.                     if (_DEBUG_HEAD) {
  1419.                       if (ioinfo) {
  1420.                         fprintf(ioinfo,"\r\nresponse for %s%s:\r\n",back[i].url_adr,back[i].url_fil);
  1421.                         fprintf(ioinfo,"(Buffer) Status-Code=%d\r\n",back[i].r.statuscode);
  1422.                         fflush(ioinfo);
  1423.                       }                    // en-tΩte
  1424.                     }
  1425.                       
  1426.                     // header // ** !attention! HTTP/0.9 non supportΘ
  1427.                     do {
  1428.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);          
  1429. #if HDEBUG
  1430.                       printf("(buffer)>%s\n",rcvd);      
  1431. #endif
  1432.                       if (_DEBUG_HEAD) {
  1433.                         if (ioinfo) {
  1434.                           fprintf(ioinfo,"(buffer)>%s\r\n",rcvd);      
  1435.                           fflush(ioinfo);
  1436.                         }
  1437.                       }
  1438.  
  1439.                       if (strnotempty(rcvd))
  1440.                         treathead(opt->cookie,back[i].url_adr,back[i].url_fil,&back[i].r,rcvd);  // traiter
  1441.                       
  1442.                       // parfois les serveurs buggΘs renvoient un content-range avec un 200
  1443.                       if (back[i].r.statuscode==200)  // 'OK'
  1444.                         if (strfield(rcvd,"content-range:"))  // Avec un content-range: relisez les RFC..
  1445.                           back[i].r.statuscode=206;    // FORCER A 206 !!!!!
  1446.                         
  1447.                     } while(strnotempty(rcvd));
  1448.                     // ----------------------------------------                    
  1449.                     
  1450.                     // libΘrer mΘmoire  -- aprΦs! --
  1451.                     if (back[i].r.adr!=NULL) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1452.  
  1453.                     
  1454.  
  1455.  
  1456.                     /* 
  1457.                        Status code and header-response hacks
  1458.                     */
  1459.                     
  1460.                     // Check response : 203 == 200
  1461.                     if (back[i].r.statuscode==203) {  // 'Non-Authoritative Information'
  1462.                       back[i].r.statuscode=200;       // forcer "OK"
  1463.                     }
  1464.                     
  1465.  
  1466.                     // Various hacks to limit re-transfers when updating a mirror
  1467.                     if (opt->sizehack) {
  1468.                       // We already have the file
  1469.                       // and ask the remote server for an update
  1470.                       // Some servers, especially dynamic pages severs, always
  1471.                       // answer that the page has been modified since last visit
  1472.                       // And answer with a 200 (OK) response, and the same page
  1473.                       // If the size is the same, and the option has been set, we assume
  1474.                       // that the file is identical - and therefore let's break the connection
  1475.                       if (back[i].is_update) {          // mise α jour
  1476.                         if (back[i].r.statuscode==200) {  // 'OK'
  1477.                           htsblk r = cache_read(opt,cache,back[i].url_adr,back[i].url_fil,NULL);    // lire entrΘe cache
  1478.                           if (r.statuscode == 200) {  // OK pas d'erreur cache
  1479.                             LLint len1,len2;
  1480.                             len1=r.totalsize;
  1481.                             len2=back[i].r.totalsize;
  1482.                             if (r.size>0)
  1483.                               len1=r.size;
  1484.                             if (len1>0) {
  1485.                               if (len1 == len2) {             // tailles identiques
  1486.                                 back[i].r.statuscode=304;     // forcer NOT MODIFIED
  1487.                                 deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1488.                                 if ((opt->debug>1) && (opt->log!=NULL)) {
  1489.                                   fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (same size), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1490.                                 }
  1491.                               }
  1492.                             }
  1493.                           } else {
  1494.                             if (opt->errlog!=NULL) {
  1495.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"File seems complete (same size), but there was a cache read error: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1496.                             }
  1497.                           }
  1498.                         }
  1499.                       }
  1500.                     }
  1501.                     /* 
  1502.                     End of status code and header-response hacks
  1503.                     */
  1504.                     
  1505.                     
  1506.                     
  1507.                     /* Interdiction taille par le wizard? */
  1508.                     if (back[i].r.soc!=INVALID_SOCKET) {
  1509.                       if (!back_checksize(opt,&back[i],1)) {
  1510.                         back[i].status=0;  // FINI
  1511.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1512.                         if (!back[i].testmode)
  1513.                           strcpy(back[i].r.msg,"File too big");
  1514.                         else
  1515.                           strcpy(back[i].r.msg,"Test: File too big");
  1516.                       }
  1517.                     }
  1518.                     
  1519.                     /* sinon, continuer */
  1520.                     /* if (back[i].r.soc!=INVALID_SOCKET) {   // ok rΘcupΘrer body? */
  1521.                     // head: terminΘ
  1522.                     if (back[i].head_request) {
  1523.                       if ((opt->debug>1) && (opt->log!=NULL)) {
  1524.                         fspc(opt->log,"debug"); fprintf(opt->log,"Tested file: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1525.                       }
  1526. #if HTS_DEBUG_CLOSESOCK
  1527.                       DEBUG_W("back_wait(head request): deletehttp\n");
  1528. #endif
  1529.                       // Couper connexion
  1530.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1531.                       back[i].status=0;  // terminΘ
  1532.                     }
  1533.                     // traiter une Θventuelle erreur 304 (cache α jour utilisable)
  1534.                     else if (back[i].r.statuscode==304) {  // document α jour dans le cache
  1535.                       // lire dans le cache
  1536.                       // ** NOTE: pas de vΘrif de la taille ici!!
  1537. #if HTS_DEBUG_CLOSESOCK
  1538.                       DEBUG_W("back_wait(file is not modified): deletehttp\n");
  1539. #endif
  1540.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1541.                       back[i].r=cache_read(opt,cache,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  1542.                       if (!back[i].r.location)
  1543.                         back[i].r.location=back[i].location_buffer;
  1544.                       else {        /* recopier */
  1545.                         strcpy(back[i].location_buffer,back[i].r.location);
  1546.                         back[i].r.location=back[i].location_buffer;
  1547.                       }
  1548.                       if (back[i].r.statuscode!=-1) { // pas d'erreur de lecture
  1549.                         back[i].status=0;         // OK prΩt
  1550.                         back[i].r.notmodified=1;  // NON modifiΘ!
  1551.                         if ((opt->debug>0) && (opt->log!=NULL)) {
  1552.                           fspc(opt->log,"debug"); fprintf(opt->log,"File loaded after test from cache: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1553.                         }
  1554. #if DEBUGCA
  1555.                         printf("..document α jour aprΦs requΦte: %s%s\n",back[i].url_adr,back[i].url_fil);
  1556. #endif
  1557.                         
  1558.                         //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  1559.                       } else {  // erreur
  1560.                         back[i].status=0;  // terminΘ
  1561.                         //printf("erreur cache\n");
  1562.                         
  1563.                       } 
  1564.                       
  1565.                     } else if ((back[i].r.statuscode==301)
  1566.                       || (back[i].r.statuscode==302)
  1567.                       || (back[i].r.statuscode==303)
  1568.                       || (back[i].r.statuscode==307)
  1569.                       || (back[i].r.statuscode==412)
  1570.                       || (back[i].r.statuscode==416)
  1571.                       ) {   // Ne pas prendre le html, erreurs connues et gΘrΘes
  1572. #if HTS_DEBUG_CLOSESOCK
  1573.                       DEBUG_W("back_wait(301,302,303,307,412,416..): deletehttp\n");
  1574. #endif
  1575.                       // Couper connexion
  1576.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1577.                       back[i].status=0;  // terminΘ
  1578.                       
  1579.                     } else {    // il faut aller le chercher
  1580.                       
  1581.                       // effacer buffer (requΦte)
  1582.                       if (back[i].r.adr!=NULL) {
  1583.                         freet(back[i].r.adr);
  1584.                         back[i].r.adr=NULL;
  1585.                       }
  1586.                       back[i].r.size=0;                                 
  1587.                       
  1588.                       // traiter 206 (partial content)
  1589.                       // xxc SI CHUNK VERIFIER QUE CA MARCHE??
  1590.                       if (back[i].r.statuscode==206) {  // on nous envoie un morceau (la fin) coz une partie sur disque!
  1591.                         LLint sz=fsize(back[i].url_sav);
  1592. #if HDEBUG
  1593.                         printf("partial content: "LLintP" on disk..\n",(LLint)sz);
  1594. #endif
  1595.                         if (sz>=0) {
  1596.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1597.                             if (opt->getmode&2) {    // on peut ecrire des non html  **sinon ben euhh sera interceptΘ plus loin, donc rap sur ce qui va sortir**
  1598.                               filenote(back[i].url_sav,NULL);    // noter fichier comme connu
  1599.                               back[i].r.out=fopen(fconv(back[i].url_sav),"ab");  // append
  1600.                               if (back[i].r.out) {
  1601.                                 back[i].r.is_write=1;    // Θcrire
  1602.                                 back[i].r.size=sz;    // dΘja Θcrit
  1603.                                 back[i].r.statuscode=200;  // Forcer 'OK'
  1604.                                 if (back[i].r.totalsize>0)
  1605.                                   back[i].r.totalsize+=sz;    // plus en fait
  1606.                                 fseek(back[i].r.out,0,SEEK_END);  // α la fin
  1607. #if HDEBUG
  1608.                                 printf("continue interrupted file\n");
  1609. #endif
  1610.                               } else {    // On est dans la m**
  1611.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1612.                                 strcpy(back[i].r.msg,"Can not open partial file");
  1613.                               }
  1614.                             }
  1615.                           } else {    // mΘmoire
  1616.                             FILE* fp=fopen(fconv(back[i].url_sav),"rb");
  1617.                             if (fp) {
  1618.                               LLint alloc_mem=sz + 1;
  1619.                               if (back[i].r.totalsize>0)
  1620.                                 alloc_mem+=back[i].r.totalsize;            // AJOUTER RESTANT!
  1621.                               if ( (back[i].r.adr=(char*) malloct((INTsys) alloc_mem)) ) {
  1622.                                 back[i].r.size=sz;
  1623.                                 if (back[i].r.totalsize>0)
  1624.                                   back[i].r.totalsize+=sz;    // plus en fait
  1625.                                 if (((int) fread(back[i].r.adr,1,(INTsys)sz,fp)) != sz) {
  1626.                                   back[i].status=0;  // terminΘ (voir plus loin)
  1627.                                   strcpy(back[i].r.msg,"Can not read partial file");
  1628.                                 } else {
  1629.                                   back[i].r.statuscode=200;  // Forcer 'OK'
  1630. #if HDEBUG
  1631.                                   printf("continue in mem interrupted file\n");
  1632. #endif
  1633.                                 }
  1634.                               } else {
  1635.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1636.                                 strcpy(back[i].r.msg,"No memory for partial file");
  1637.                               }
  1638.                             } else {  // Argh.. 
  1639.                               back[i].status=0;  // terminΘ (voir plus loin)
  1640.                               strcpy(back[i].r.msg,"Can not open partial file");
  1641.                             }
  1642.                           }
  1643.                         } else {    // Non trouvΘ??
  1644.                           back[i].status=0;  // terminΘ (voir plus loin)
  1645.                           strcpy(back[i].r.msg,"Can not find partial file");
  1646.                         }
  1647.                         // Erreur?
  1648.                         if (back[i].status==0) {
  1649.                           if (back[i].r.soc!=INVALID_SOCKET) {
  1650. #if HTS_DEBUG_CLOSESOCK
  1651.                             DEBUG_W("back_wait(206 solve problems): deletehttp\n");
  1652. #endif
  1653.                             deletehttp(&back[i].r);
  1654.                           }
  1655.                           back[i].r.soc=INVALID_SOCKET;
  1656.                           //back[i].r.statuscode=206;  ????????
  1657.                           back[i].r.statuscode=-5;
  1658.                           if (strnotempty(back[i].r.msg))
  1659.                             strcpy(back[i].r.msg,"Error attempting to solve status 206 (partial file)");
  1660.                         }
  1661.                       }
  1662.                       
  1663.                       if (back[i].status!=0) {  // non terminΘ (erreur)
  1664.                         if (!back[i].testmode) {    // fichier normal
  1665.                           
  1666.                           if (!back[i].r.is_chunk) {    // pas de chunk
  1667.                             //if (back[i].r.http11!=2) {    // pas de chunk
  1668.                             back[i].is_chunk=0;
  1669.                             back[i].status=1;     // start body
  1670.                           } else {
  1671. #if CHUNKDEBUG==1
  1672.                             printf("chunk encoding detected %s..\n",back[i].url_fil);
  1673. #endif
  1674.                             back[i].is_chunk=1;
  1675.                             back[i].chunk_adr=NULL;
  1676.                             back[i].chunk_size=0;
  1677.                             back[i].status=98;    // start body wait chunk
  1678.                           }
  1679.                           if (back[i].rateout>0) {
  1680.                             back[i].rateout_time=time_local();  // refresh pour transfer rate
  1681.                           }
  1682. #if HDEBUG
  1683.                           printf("(buffer) start body!\n");
  1684. #endif
  1685.                         } else {     // mode test, ne pas passer en 1!!
  1686.                           back[i].status=0;    // READY
  1687. #if HTS_DEBUG_CLOSESOCK
  1688.                           DEBUG_W("back_wait(test ok): deletehttp\n");
  1689. #endif
  1690.                           deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1691.                           if (back[i].r.statuscode==200) {
  1692.                             strcpy(back[i].r.msg,"Test: OK");
  1693.                             back[i].r.statuscode=-10;    // test rΘussi
  1694.                           }
  1695.                           else {    // test a ΘchouΘ, on ne change rien sauf que l'erreur est α titre indicatif
  1696.                             char tempo[1000];
  1697.                             strcpy(tempo,back[i].r.msg);
  1698.                             strcpy(back[i].r.msg,"Test: ");
  1699.                             strcat(back[i].r.msg,tempo);
  1700.                           }
  1701.                           
  1702.                         }
  1703.                       }
  1704.                       
  1705.                       } 
  1706.                       
  1707.                       /*}*/
  1708.                       
  1709.                   }  // si LF
  1710.                 }  // r.size>2
  1711.               }  // si == 99
  1712.               
  1713.             } // si pas d'erreurs
  1714. #if BDEBUG==1
  1715.             printf("bytes overall: %d\n",back[i].r.size);
  1716. #endif
  1717.           }  // donnΘes dispo
  1718.           
  1719.           // en cas d'erreur cl, supprimer Θventuel fichier sur disque
  1720. #if HTS_REMOVE_BAD_FILES
  1721.           if (back[i].status<0) {
  1722.             if (!back[i].testmode) {    // pas en test
  1723.               remove(back[i].url_sav);    // Θliminer fichier (endommagΘ)
  1724.               //printf("&& %s\n",back[i].url_sav);
  1725.             }
  1726.           }
  1727. #endif
  1728.  
  1729.           /* funny log for commandline users */
  1730.           if (!opt->quiet) {  // petite animation
  1731.             if (opt->verbosedisplay) {
  1732.               if (back[i].status==0) {
  1733.                 if (back[i].r.statuscode==200)
  1734.                   printf("* %s%s ("LLintP" bytes) - OK\33[K\r",back[i].url_adr,back[i].url_fil,back[i].r.size);
  1735.                 else
  1736.                   printf("* %s%s ("LLintP" bytes) - %d\33[K\r",back[i].url_adr,back[i].url_fil,back[i].r.size,back[i].r.statuscode);
  1737.                 fflush(stdout);
  1738.               }
  1739.             }
  1740.           }
  1741.           
  1742.  
  1743.       } // status>0
  1744.     }  // for
  1745.     
  1746.     // vΘrifier timeouts
  1747.     if (gestion_timeout) {
  1748.       double act;
  1749.       act=time_local();    // temps en secondes
  1750.       for(i=0;i<back_max;i++) {
  1751.         if (back[i].status>0) {  // rΘception/connexion/..
  1752.           if (back[i].timeout>0) {
  1753.             //printf("time check %d\n",((int) (act-back[i].timeout_refresh))-back[i].timeout);
  1754.             if (((int) (act-back[i].timeout_refresh))>=back[i].timeout) {
  1755.               if (back[i].r.soc!=INVALID_SOCKET) {
  1756. #if HTS_DEBUG_CLOSESOCK
  1757.                 DEBUG_W("back_wait(timeout): deletehttp\n");
  1758. #endif
  1759.                 deletehttp(&back[i].r);
  1760.               }
  1761.               back[i].r.soc=INVALID_SOCKET;
  1762.               back[i].r.statuscode=-2;
  1763.               if (back[i].status==100)
  1764.                 strcpy(back[i].r.msg,"Connect Time Out");
  1765.               else if (back[i].status==101)
  1766.                 strcpy(back[i].r.msg,"DNS Time Out");
  1767.               else
  1768.                 strcpy(back[i].r.msg,"Receive Time Out");
  1769.               back[i].status=0;  // terminΘ
  1770.             } else if ((back[i].rateout>0) && (back[i].status<99)) {
  1771.               if (((int) (act-back[i].rateout_time))>=HTS_WATCHRATE) {   // checker au bout de 15s
  1772.                 if ( (int) ((back[i].r.size)/(act-back[i].rateout_time)) < back[i].rateout ) {  // trop lent
  1773.                   back[i].status=0;  // terminΘ
  1774.                   if (back[i].r.soc!=INVALID_SOCKET) {
  1775. #if HTS_DEBUG_CLOSESOCK
  1776.                     DEBUG_W("back_wait(rateout): deletehttp\n");
  1777. #endif
  1778.                     deletehttp(&back[i].r);
  1779.                   }
  1780.                   back[i].r.soc=INVALID_SOCKET;
  1781.                   back[i].r.statuscode=-3;
  1782.                   strcpy(back[i].r.msg,"Transfer Rate Too Low");
  1783.                 }
  1784.               }
  1785.             }
  1786.           }
  1787.         }
  1788.       }
  1789.     }
  1790.     max_loop--;
  1791. #if HTS_ANALYSTE==2
  1792.     max_loop_chk++;
  1793. #endif
  1794.   } while((busy) && (max_loop>0));
  1795. #if HTS_ANALYSTE==2
  1796.   if (!busy) {
  1797.     if (max_loop_chk>=1) {
  1798.       Sleep(10);    // un tite pause pour Θviter les lag..
  1799.     }
  1800.   }
  1801. #endif
  1802. }
  1803.  
  1804. int back_checksize(httrackp* opt,lien_back* eback,int check_only_totalsize) {
  1805.   LLint size_to_test;
  1806.   if (check_only_totalsize)
  1807.     size_to_test=eback->r.totalsize;
  1808.   else
  1809.     size_to_test=max(eback->r.totalsize,eback->r.size);
  1810.   if (size_to_test>=0) {
  1811.     
  1812.     /* Interdiction taille par le wizard? */
  1813.     if (hts_testlinksize(opt,eback->url_adr,eback->url_fil,(eback->r.totalsize+1023)/1024)==-1) {
  1814.       return 0;     /* interdit */
  1815.     }                     
  1816.     
  1817.     /* vΘrifier taille classique (heml et non html) */
  1818.     if ((istoobig(size_to_test,eback->maxfile_html,eback->maxfile_nonhtml,eback->r.contenttype))) {
  1819.       return 0;     /* interdit */
  1820.     }
  1821.   }
  1822.   return 1;
  1823. }
  1824.  
  1825.  
  1826. // octets transfΘrΘs + add
  1827. LLint back_transfered(LLint nb,lien_back* back,int back_max) {
  1828.   int i;
  1829.   // ajouter octets en instance
  1830.   for(i=0;i<back_max;i++)
  1831.     if ((back[i].status>0) && (back[i].status<99))
  1832.       nb+=back[i].r.size;
  1833.   return nb;      
  1834. }
  1835.  
  1836. // infos backing
  1837. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  1838. void back_info(lien_back* back,int i,int j,FILE* fp) {
  1839.   if (back[i].status>=0) {
  1840.     char s[256]; 
  1841.          s[0]='\0';
  1842.     back_infostr(back,i,j,s);
  1843.     strcat(s,LF);
  1844.     fprintf(fp,"%s",s);
  1845.   }
  1846. }
  1847.  
  1848. // infos backing
  1849. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  1850. void back_infostr(lien_back* back,int i,int j,char* s) {
  1851.   if (back[i].status>=0) {
  1852.     int aff=0;
  1853.     if (j & 1) {
  1854.       if (back[i].status==100) {
  1855.         strcat(s,"CONNECT ");
  1856.       } else if (back[i].status==99) {
  1857.         strcat(s,"INFOS ");
  1858.         aff=1;
  1859.       } else if (back[i].status==98) {
  1860.         strcat(s,"INFOSC");             // infos chunk
  1861.         aff=1;
  1862.       }
  1863.       else if (back[i].status>0) {
  1864. #if HTS_ANALYSTE==2
  1865.         strcat(s,"WAIT ");
  1866. #else
  1867.         strcat(s,"RECEIVE "); 
  1868. #endif
  1869.         aff=1; 
  1870.       }
  1871.     } 
  1872.     if (j & 2) {
  1873.       if (back[i].status==0) {
  1874.         switch (back[i].r.statuscode) {
  1875.         case 200:
  1876.           strcat(s,"READY ");
  1877.           aff=1;
  1878.           break;
  1879. #if HTS_ANALYSTE==2
  1880.         default:
  1881.           strcat(s,"ERROR ");
  1882.           break;
  1883. #else
  1884.         case -1:
  1885.           strcat(s,"ERROR ");
  1886.           aff=1;
  1887.           break;
  1888.         case -2:
  1889.           strcat(s,"TIMEOUT ");
  1890.           aff=1;
  1891.           break;
  1892.         case -3:
  1893.           strcat(s,"TOOSLOW ");
  1894.           aff=1;
  1895.           break;
  1896.         case 400:
  1897.           strcat(s,"BADREQUEST ");
  1898.           aff=1;
  1899.           break;
  1900.         case 401: case 403:
  1901.           strcat(s,"FORBIDDEN ");
  1902.           aff=1;
  1903.           break;
  1904.         case 404:
  1905.           strcat(s,"NOT FOUND ");
  1906.           aff=1;
  1907.           break;
  1908.         case 500:
  1909.           strcat(s,"SERVERROR ");
  1910.           aff=1;
  1911.           break;
  1912.         default:
  1913.           {
  1914.             char s2[256];
  1915.             sprintf(s2,"ERROR(%d)",back[i].r.statuscode);
  1916.             strcat(s,s2);
  1917.           }
  1918.           aff=1;
  1919. #endif
  1920.         }
  1921.       }
  1922.     }
  1923.     
  1924.     if (aff) {
  1925.       {
  1926.         char s2[256];
  1927.         sprintf(s2,"\"%s",back[i].url_adr); strcat(s,s2);
  1928.         
  1929.         if (back[i].url_fil[0]!='/') strcat(s,"/");
  1930.         sprintf(s2,"%s\" ",back[i].url_fil); strcat(s,s2);
  1931.         sprintf(s,LLintP" "LLintP" ",back[i].r.size,back[i].r.totalsize); strcat(s,s2);
  1932.       }
  1933.     }
  1934.   }
  1935. }
  1936.  
  1937. // -- backing --
  1938.  
  1939. #undef test_flush
  1940.